package fr.neyb.wesb.core.data.descriptors.field.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import fr.neyb.framework.util.Tools;
import fr.neyb.wesb.core.data.content.Field;
import fr.neyb.wesb.core.data.descriptors.field.FieldDescriptor;

public abstract class AbstractFieldDescritor<T extends Field> implements
		FieldDescriptor {

	public static interface CSValidator<T extends Field> {
		boolean validate(T field);
	}

	private final Class<T> clazz;
	private final CSValidator<T>[] omnipresentValidators;
	private final List<CSValidator<T>> validators = new ArrayList<CSValidator<T>>();

	@SafeVarargs
	public AbstractFieldDescritor(Class<T> clazz,
			CSValidator<T>... omnipresentValidators) {
		this.clazz = clazz;
		this.omnipresentValidators = Arrays.copyOf(omnipresentValidators,
				omnipresentValidators.length);
	}

	public final boolean isRightTypedField(Field f) {
		return clazz.isInstance(f);
	}

	public final void addvalidator(CSValidator<T> val) {
		validators.add(val);
	}

	@Override
	public int hashCode() {
		return Tools.hashcode(validators.hashCode());
	}

	public final void removeAllValidator() {
		validators.clear();
	}

	@Override
	public final boolean validateField(Field f) {
		if (!isRightTypedField(f))
			return false;

		T fAsT = clazz.cast(f);
		for (CSValidator<T> validator : omnipresentValidators) {
			if (!validator.validate(fAsT))
				return false;
		}
		for (CSValidator<T> validator : validators) {
			if (!validator.validate(fAsT))
				return false;
		}
		return true;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!(obj instanceof AbstractFieldDescritor))
			return false;
		AbstractFieldDescritor<?> fD = (AbstractFieldDescritor<?>) obj;
		return Tools.nullOrEqual(validators, fD.validators);
	}

	protected CSValidator<? extends Field> getOmniValidator(int index) {
		return omnipresentValidators[index];
	}

}
